package com.wang.lottery.domain.strategy.service.algorithm.impl;

import com.wang.lottery.domain.strategy.model.vo.AwardRateInfo;
import com.wang.lottery.domain.strategy.service.algorithm.BaseAlgorithm;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;

/**
 * @author wjh
 * @create 2023-11-01 15:00
 * 必中奖策略抽奖，排掉已经中奖的概率，重新计算中奖范围
 * 总体概率：如果A奖品抽空后，B和C奖品的概率按照 3:5 均分，相当于B奖品中奖概率由 0.3 升为 0.375
 * 算法描述：分别把A、B、C对应的概率值转换成阶梯范围值，A=(0~0.2」、B=(0.2-0.5」、C=(0.5-1.0」，
 * 当使用随机数方法生成一个随机数后，与阶梯范围值进行循环比对找到对应的区域，匹配到中奖结果。
 */
@Component("defaultRateRandomDrawAlgorithm")
public class DefaultRateRandomDrawAlgorithm extends BaseAlgorithm {
    /**
     * 使用随机数抽奖，排除已经抽完的奖品，返回中奖结果
     *
     * @param strategyId      策略id
     * @param excludeAwardIds 排除的奖品id列表
     * @return 中奖的奖品id，没中奖就返回“未中奖”
     */
    @Override
    public String randomDraw(Long strategyId, List<String> excludeAwardIds) {
        
        List<AwardRateInfo> awardRateInfoList = super.awardRateInfoMap.get(strategyId);
        //先排除抽完的奖品
        List<AwardRateInfo> differenceAwardRateList = new ArrayList<>();
        //计算剩余奖品的中奖概率的总和
        BigDecimal differenceDenominator = BigDecimal.ZERO;
        for (AwardRateInfo awardRateInfo : awardRateInfoList) {
            if (excludeAwardIds.contains(awardRateInfo.getAwardId())) {
                continue;
            }
            differenceAwardRateList.add(awardRateInfo);
            differenceDenominator = differenceDenominator.add(awardRateInfo.getAwardRate());
        }
        //前置判断，如果抽奖池没有奖品，就返回空“未中奖”
        if (differenceAwardRateList.size() == 0) {
            return null;
        }
        //前置判断，如果抽奖池只有一个奖品，就返回该奖品id，因为这是必中奖的策略，所以无需往后执行
        if (differenceAwardRateList.size() == 1) {
            return differenceAwardRateList.get(0).getAwardId();
        }
        // 获取0~100随机概率值
        SecureRandom random = new SecureRandom();
        //random.nextInt(100)的范围是[0，100），+1就成了[1，100]
        int randomVal = random.nextInt(100) + 1;
        String awardId = null;
        int cursorVal = 0;
        // 循环获取奖品
        for (AwardRateInfo awardRateInfo : differenceAwardRateList) {
            int rateVal = awardRateInfo.getAwardRate().divide(differenceDenominator, 2, RoundingMode.UP).multiply(new BigDecimal(100)).intValue();
            if (randomVal <= (rateVal + cursorVal)) {
                awardId = awardRateInfo.getAwardId();
                break;
            }
            cursorVal += rateVal;
        }
        return awardId;
    }
    /**
     * 判断是否做了数据初始化
     *
     * @param strategyId 策略id
     * @return true为已经初始化，false为未初始化
     */
    @Override
    public boolean isExistRateTuple(Long strategyId) {
        return  awardRateInfoMap.containsKey(strategyId);
    }
}
